package prj5;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import cs2.*;

/**
 *
 * SpaceWindow creates and updates the front-end of this simulation, to make a
 * visual representation of the space colonies game. To use this class, just
 * instantiate an object in the ColonyReader Class and pass a ColonyCalculator
 * object. This class is currently hardcoded for 3 planets.
 * @author CS2114 course
 * @version 2020.10.21 b
 *
 */
public class GUIWindow {

    private Window window;
    private Button sortByAlphaButton;
    private Button quitButton;
    private Button refreshButton;
    private Button sortByCfrButton;
    private Button representButtonDC;
    private Button representButtonGA;
    private Button representButtonMD;
    private Button representButtonNC;
    private Button representButtonTN;
    private Button representButtonVA;
    private static int DISPLAY_FACTOR = 10;
    private static int PLANET_HEIGHT = 7;
    private static int PLANET_SIZE = PLANET_HEIGHT * DISPLAY_FACTOR;
    private static int QUEUE_STARTX = 50;
    private static int QUEUE_STARTY = 75;
    private static int CIRCLE_SIZE = 4;
    private Shape[] planetShapes = new Shape[3];
    private static Color[] PLANET_COLORS = new Color[7];
    private List<Data> datas;
    private String refreshStateName = "DC";
    private int refreshSoutFlag = 0;
    private int width = 600;
    private int height = 540;

    /**
     * Constructor.
     * @param dataList initial data list
     */
    public GUIWindow(List<Data> dataList) {
        datas = dataList;
        window = new Window();
        window.setTitle("Space Colony Placement");
        window.setSize(600, 540);

        sortByAlphaButton = new Button("Sort by Alpha");
        sortByAlphaButton.onClick(this::clickedSortByAlpha);
        quitButton = new Button("Quit");
        quitButton.onClick(this::clickedQuit);
        sortByCfrButton = new Button("Sort by CFR");
        sortByCfrButton.onClick(this::clickedSortByCfr);
        refreshButton = new Button("Refresh");
        refreshButton.onClick(this::clickedRefresh);

        representButtonDC = new Button("Representation DC");
        representButtonDC.onClick(this::clickedDC);
        representButtonGA = new Button("Representation GA");
        representButtonGA.onClick(this::clickedGA);
        representButtonMD = new Button("Representation MD");
        representButtonMD.onClick(this::clickedMD);
        representButtonNC = new Button("Representation NC");
        representButtonNC.onClick(this::clickedNC);
        representButtonTN = new Button("Representation TN");
        representButtonTN.onClick(this::clickedTN);
        representButtonVA = new Button("Representation VA");
        representButtonVA.onClick(this::clickedVA);

        window.addButton(sortByAlphaButton, WindowSide.NORTH);
        window.addButton(quitButton, WindowSide.NORTH);
        window.addButton(refreshButton, WindowSide.NORTH);
        window.addButton(sortByCfrButton, WindowSide.NORTH);
        window.addButton(representButtonDC, WindowSide.SOUTH);
        window.addButton(representButtonGA, WindowSide.SOUTH);
        window.addButton(representButtonMD, WindowSide.SOUTH);
        window.addButton(representButtonNC, WindowSide.SOUTH);
        window.addButton(representButtonTN, WindowSide.SOUTH);
        window.addButton(representButtonVA, WindowSide.SOUTH);
        drawBarChart(refreshStateName, refreshSoutFlag);
        initButtons();
    }

    /**
     * Refresh Data
     * @param widget
     */
    private void clickedRefresh(Widget widget) {
        drawBarChart(refreshStateName, refreshSoutFlag);
    }

    /**
     * Display the data of va area
     * @param widget
     */
    private void clickedVA(Widget widget) {
        drawBarChart("VA", 0);
    }

    /**
     * Display the data of tn area
     * @param widget
     */
    private void clickedTN(Widget widget) {
        drawBarChart("TN", 0);
    }

    /**
     * Display the data of nc area
     * @param widget
     */
    private void clickedNC(Widget widget) {
        drawBarChart("NC", 0);
    }

    /**
     * Display the data of md area
     * @param widget
     */
    private void clickedMD(Widget widget) {
        drawBarChart("MD", 0);
    }

    /**
     * Display the data of ga area
     * @param widget
     */
    private void clickedGA(Widget widget) {
        drawBarChart("GA", 0);
    }

    /**
     * Display the data of dc area
     * @param widget
     */
    private void clickedDC(Widget widget) {
        drawBarChart("DC", 0);
    }

    /**
     * sort data by alpha
     * @param widget
     */
    private void clickedSortByAlpha(Widget widget) {
        drawBarChart(refreshStateName, 1);
    }

    /**
     * sort data by cftr
     * @param widget
     */
    private void clickedSortByCfr(Widget widget) {
        drawBarChart(refreshStateName, 2);
    }

    /**
     * clickedQuit.
     * @param widget
     */
    private void clickedQuit(Widget widget) {
        System.exit(0);
    }

    /**
     * When the window is displayed the first time buttons are disabled if queue
     * is
     * empty otherwise enable
     */
    private void initButtons() {
        sortByAlphaButton.enable();
        quitButton.enable();
        sortByCfrButton.enable();
    }

    /**
     * refresh width height
     */
    private void refreshWidthHeight() {
        width = window.getWidth() - 20;
        height = window.getHeight() - 120;
    }

    /**
     * use findByStateName and createBarChart to draw bar chart.
     * @param stateName
     * @param soutFlag
     */
    private void drawBarChart(String stateName, int soutFlag) {
        refreshSoutFlag = soutFlag;
        refreshStateName = stateName;
        window.removeAllShapes();
        Data data = findByStateName(stateName);
        List<Shape> shapes = createBarChart(data, soutFlag);
        for (Shape shape:shapes) {
            window.addShape(shape);
        }
    }

    /**
     * find data by stateName.
     * @param stateName stateName
     * @return state date
     */
    private Data findByStateName(String stateName) {
        for (Data data:datas) {
            if (stateName.equals(data.getStateName())) {
                return data;
            }
        }
        return null;
    }

    /**
     * create bar chart.
     * @param data Races Data
     * @param soutFlag sout flag
     * @return shape of bar chart
     */
    private List<Shape> createBarChart(Data data, int soutFlag) {
        List<RaceStatusData> raceStatusDatas;
        switch (soutFlag) {
            case 1:
                raceStatusDatas = data.getRaceSortByAipha();
                break;
            case 2:
                raceStatusDatas = data.getRaceSortByCFR();
                break;
            default:
                raceStatusDatas = data.getRaceOfStateData();
                break;
        }
        refreshWidthHeight();
        List<Shape> shapeList = new ArrayList();
        TextShape textShape = new TextShape(0, 0, data.getStateName());
        textShape.setX((width - textShape.getWidth()) / 2);
        shapeList.add(textShape);
        int gap = width / 11;
        int yBegin = textShape.getHeight();
        int yEnd = height - 45;
        int yCfr = height - 20;
        int yRaceName = height - 40;
        int centralAxis = (int) (1.5 * gap);
        for (RaceStatusData raceStatusData:raceStatusDatas) {
            double cfr;
            if (raceStatusData.getCfr().equals("-1")) {
                cfr = Double.NaN;
            }
            else {
                cfr = Double.valueOf(raceStatusData.getCfr());
            }
            textShape = new TextShape(centralAxis, yCfr, cfr + "%");
            textShape.setX(centralAxis - textShape.getWidth() / 2);
            shapeList.add(textShape);

            textShape = new TextShape(centralAxis, yRaceName,
                    raceStatusData.getRaceName());
            textShape.setX(centralAxis - textShape.getWidth() / 2);
            shapeList.add(textShape);

            int heightShape = (int) ((yEnd - yBegin) * cfr / 100);
            int yShape = yEnd - heightShape;
            Shape shape = new Shape(centralAxis - gap / 2,
                    yShape, gap, heightShape, Color.CYAN);
            shapeList.add(shape);
            centralAxis += 2 * gap;
        }
        return shapeList;
    }
}
